-- DungeonLegacyM
-- Created by chengb Jan/22/2015
-- 地牢遗产功能

module("DungeonLegacyM", package.seeall);

-- 获取遗产信息
function getLegacyInfo()
    local dungeonId = DungeonM.getDungeonId();
    local layer = DungeonM.currentLayer();

    if not dungeonId or not layer then
        return nil;
    end

    local dungeonLegacy = ME.user.dbase:query("dungeon_legacy", {});
    if not dungeonLegacy[dungeonId] then
        return nil;
    end

    if DungeonInstanceM.isInInstance() then
        -- 副本中没有遗产信息
        return nil;
    end

    return dungeonLegacy[dungeonId][layer];
end

-- 获取属性遗产
function getLegacyAttrib(legacyInfo)
    if not legacyInfo then
        return {};
    end

    local attribBonus = {};
    local itemBonus = {};
    for key, value in pairs(legacyInfo) do
        if type(key) == "string" then
            table.insert(attribBonus, { 2,  key, value });
        end
    end

    -- 对属性进行排序
    if #table.keys(attribBonus) > 0 then
        local function sortAttrib(attrib1, attrib2)
            -- 根据fields表中的sort字段排序
            local sortPrio1 = FieldsM.query(attrib1[2], "sort");
            local sortPrio2 = FieldsM.query(attrib2[2], "sort");
            if sortPrio1 < sortPrio2 then
                return true;
            else
                return false;
            end
        end
        table.sort(attribBonus, sortAttrib);
    end

    return attribBonus;
end

-- 获取宝物遗产
function getLegacyEquip(legacyInfo)
    if not legacyInfo then
        return {};
    end

    local itemBonus = {};

    for key, value in pairs(legacyInfo) do
        if type(key) == "number" then
            if EquipM.isEquipment(key) then
                table.insert(itemBonus, { 1, key, value });
            end
        end
    end

    return itemBonus;
end

-- 获取卷轴遗产
function getLegacySpell(legacyInfo)
    if not legacyInfo then
        return {};
    end

    local itemBonus = {};

    for key, value in pairs(legacyInfo) do
        if type(key) == "number" then
            if SpellM.isSpell(key) then
                table.insert(itemBonus, { 1, key, value });
            end
        end
    end

    return itemBonus;
end

-- 获取遗产描述
function getLegacyDesc(legacyInfo)
    if not legacyInfo then
        return "";
    end

    local attribBonus = {};
    local itemBonus = {};
    local keyList = table.keys(legacyInfo);

    for _, key in pairs(keyList) do
        if type(key) == "string" then
            table.insert(attribBonus, key);
        elseif type(key) == "number" then
            table.insert(itemBonus, key);
        else
            -- 暂不处理
        end
    end

    -- 对属性进行排序
    if #attribBonus > 0 then
        local function sortAttrib(attrib1, attrib2)
            -- 根据fields表中的sort字段排序
            local sortPrio1 = FieldsM.query(attrib1, "sort");
            local sortPrio2 = FieldsM.query(attrib2, "sort");
            if sortPrio1 < sortPrio2 then
                return true;
            else
                return false;
            end
        end
        table.sort(attribBonus, sortAttrib);
    end

    local str = getLocStr("take_legacy_done");

    -- 拼接属性奖励
    for _, attrib in pairs(attribBonus) do
        local fieldName = FieldsM.getFieldName(attrib);
        str = str .. string.format(getLocStr("legacy_attrib_desc"), fieldName, legacyInfo[attrib]);
    end

    if #itemBonus <= 0  then
        return str;
    end

    str = str .. "\n" .. getLocStr("legacy_gain_item");

    -- 拼接物品奖励
    for _, classId in pairs(itemBonus) do
        local itemName = ItemM.query(classId, "name");
        str = str .. string.format(getLocStr("legacy_item_desc"), itemName, legacyInfo[classId]);
    end

    return str;
end

-- 清除遗产
function clearLegacy()
    local dungeonId = DungeonM.getDungeonId();
    local layer = DungeonM.currentLayer();
    if not dungeonId or not layer then
        return false;
    end

    -- 获取遗产信息
    local dungeonLegacy = ME.user.dbase:query("dungeon_legacy");
    if not dungeonLegacy[dungeonId] or
        not dungeonLegacy[dungeonId][layer] then
        return false;
    end

    -- 清除遗产信息
    dungeonLegacy[dungeonId] = nil;
    return true;
end

-- 领取遗产
function takeLegacy(pos)
    if not DungeonM.checkDungeonAction() then
        -- 经检测，不允许执行地牢行为
        return false;
    end

    local dungeonId = DungeonM.getDungeonId();
    local layer = DungeonM.currentLayer();

    -- 获取遗产信息
    local dungeonLegacy = ME.user.dbase:query("dungeon_legacy");
    if not dungeonLegacy[dungeonId] or
       not dungeonLegacy[dungeonId][layer] then
        cclog("遗产信息尚未生成，无法领取遗产。");
        return false;
    end

    local info = dungeonLegacy[dungeonId][layer];

    local bonus = {};
    for k, v in pairs(info) do
        if type(k) == "string" then
            -- 属性奖励
            table.insert(bonus, { 2, k, v });
        elseif type(k) == "number" then
            -- 物品奖励
            table.insert(bonus, { 1, k, v });
        else
            --assert(false, "奖励配置错误。");
        end
    end

    -- 排序一把，确保服务器/客户端顺序一致
    table.sort(bonus, function(a, b) return "legacy" .. a[2] < "legacy" .. b[2]; end);

    -- 执行奖励
    for _, arr in ipairs(bonus) do
        BonusM.doBonus(arr, "legacy");
    end

    -- 抛出一个回合事件
    EventMgr.fire(event.COMBAT_ROUND, { ["pos"] = pos, ["isDelay"] = true });

    -- 抛出领取遗产的事件
    EventMgr.fire(event.TAKE_LEGACY, {["pos"] = pos, ["legacy"] = info,});

    -- 清除遗产信息
    dungeonLegacy[dungeonId] = nil;

    -- 将格子设置为无效
    local grid = DungeonM.getGridByPos(pos);
    grid:changeState(GRID_STATE_DISABLE);

    -- 通知建筑事件完成
    EventMgr.fire(event.BUILDING_EVENT_DONE, {["pos"] = pos});

    -- 玩家出手
    EventMgr.fire(event.PLAYER_MOVE, pos);

    return true;
end

-- 计算复活的消耗
function calcReviveCost()
    return FormulaM.invoke("CALC_REVIVE_COST", ME.user);
end

-- 判断能否复活
function canRevive()
    if SkyInstanceM.isInSkyInstance() then
        trace("DungeonLegacyM", "天空特殊副本中不能复活。");
        return false;
    end

    if AwakeM.isInAwake() then
        trace("DungeonLegacyM", "觉醒地牢中不能复活。");
        return false;
    end

    if not UnrealDungeonM.canRevive() then
        trace("DungeonLegacyM", "特殊副本中不能复活。");
        return false;
    end

    local cost = calcReviveCost();
    if ME.user:queryAttrib(cost[2]) < cost[3] then
        return cost[2] .. "_lack";
    end

    return true;
end

-- 判断能否召唤出收魂者冈布奥
function canCallReviveSlime()
   local getSlimeTimes = FormulaM.invoke("CALC_REVIVE_TIMES_TO_GET_SPOKESMAN");
   return ME.user:getTotalReviveTimes() >= getSlimeTimes;
end

-- 复活
function revive()
    -- 经判断，无法复活
    if true ~= canRevive() then
        return false;
    end

    -- 执行消耗
    local cost = calcReviveCost();
    if not ME.user:costAttrib(cost[2], cost[3]) then
        -- 扣除失败
        return false;
    end

    -- 累积复活次数
    ME.user:setReviveTimes(ME.user:getReviveTimes() + 1);

    -- 累计总复活次数（不清除）
    ME.user:setTotalReviveTimes(ME.user:getTotalReviveTimes() + 1);

    -- 执行复活
    ME.user:revive();

    -- 抛出复活事件，revive接口里面抛出
    --EventMgr.fire(event.HERO_REVIVE);

    -- 判断是否奖励召唤者冈布奥
    if canCallReviveSlime() then
        local bonus = FormulaM.invoke("CALC_REVIVE_SPOKESMAN_BONUS");

        -- 奖励
        BonusM.doBonus(bonus, "revive_bonus");

        -- 如果是得到冈布奥，立马保存进度
        if bonus[1] == 3 then
            DungeonActionM.immediatelySave();
        end

        if bonus[1] == 1 then
            -- 播放对话
            local msgList = FormulaM.invoke("GET_SLIME_TALKS", 24, "gain_items");
            EventMgr.fire(event.SLIME_TALK, {["heroId"] = 24,
                ["msgList"] = msgList, ["endEffect"] = bonus});
            AudioM.playFx("slime_machinery_app");
        end
    end

    -- 抛出花费探索点复活
    EventMgr.fire(event.COST_SP_HERO_REVIVE);

    return true;
end

-- 标记正在播放遗产动画
function setPlayingLegacy(isPlaying)
    if isPlaying == true then
        ME.user.dbase:setTemp("playingLegacy", isPlaying);
    else
        ME.user.dbase:deleteTemp("playingLegacy");
    end
end

-- 是否在播放遗产动画
function isPlayingLegacy()
    if ME.user.dbase:queryTemp("playingLegacy") == true then
        return true;
    end
    return false;
end

-- 是否有遗产奖励
function hasLeagacy()
    -- 觉醒地牢不要遗产
    if AwakeM.isInAwake() then
        return false;
    end

    if not DungeonLegacyM.getLegacyInfo() then
        return false;
    end

    if UnrealDungeonM.isInUnreal() then
        -- 夹层中没有遗产
        return false;
    end

    return true;
end



